﻿using System;
using Microsoft.Xna.Framework;

namespace Babylon.Toolbox
{
    public abstract class CameraBase : SceneReference
    {
        Matrix projection;
        float _fieldOfView;
        public float FieldOfView
        {
            get { return _fieldOfView; }
            set
            {
                if (_fieldOfView == value)
                    return;

                _fieldOfView = value;

                UpdateProjectionMatrix();
                RaisePropertyChanged(() => FieldOfView);
            }
        }

        float _aspectRatio;
        public float AspectRatio
        {
            get { return _aspectRatio; }
            set
            {
                if (_aspectRatio == value)
                    return;

                _aspectRatio = value;

                UpdateProjectionMatrix();
                RaisePropertyChanged(() => AspectRatio);
            }
        }

        float _nearPlane;
        public float NearPlane
        {
            get { return _nearPlane; }
            set
            {
                if (_nearPlane == value)
                    return;

                _nearPlane = value;

                UpdateProjectionMatrix();
                RaisePropertyChanged(() => NearPlane);
            }
        }

        float _farPlane;
        public float FarPlane
        {
            get { return _farPlane; }
            set
            {
                if (_farPlane == value)
                    return;

                _farPlane = value;

                UpdateProjectionMatrix();
                RaisePropertyChanged(() => FarPlane);
            }
        }

        public abstract Matrix View { get; }

        public abstract Vector3 Position { get; set; }

        protected CameraBase(string name, Guid id)
            : base(name, id)
        {
            _fieldOfView = 0.8f;
            _aspectRatio = 4.0f / 3.0f;
            _nearPlane = 0.01f;
            _farPlane = 10000.0f;
            UpdateProjectionMatrix();
        }

        protected CameraBase(string name)
            : this(name, Guid.NewGuid())
        {
        }

        void UpdateProjectionMatrix()
        {
            projection = Matrix.CreatePerspectiveFieldOfView(FieldOfView, AspectRatio, NearPlane, FarPlane);
        }

        public Matrix Projection
        {
            get { return projection; }
        }
    }
}
